using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Timers;
using System.Windows.Forms;
using Timer=System.Timers.Timer;

namespace BibleScreen
{
    internal class ImageUI : IDisposable
    {
        private readonly uint slideShowDelay;

        private readonly Timer backgroundTimer;
        private readonly RectangleF frame;

        private readonly ImageSource imageSource;
        private readonly string infoMessage = "Laster Bilder...";
        private readonly ScreenSaverForm screenSaverForm;
        private readonly bool started;
        private int currentAlpha = 255;

        private int state;
        private int waitCounter;

        public ImageUI(Rectangle bounds, ImageSource imageSource, ScreenSaverForm screenSaverForm)
        {
            
            this.imageSource = imageSource;
            this.screenSaverForm = screenSaverForm;
            slideShowDelay = Options.SlideShowDelay * (1000 / 10);


            frame = new RectangleF(100, 30 + 75 + 30, bounds.Right - 200, bounds.Bottom - 130 - bounds.Bottom/5 - 30);

            backgroundTimer = new Timer {AutoReset = true, Interval = 10};

            backgroundTimer.Elapsed += backgroundTimer_Elapsed;

            if (imageSource.Current == null)
            {
                started = false;
                infoMessage = Text.NoImagesFound;
                screenSaverForm.Refresh();
            }
            else
            {
                started = true;
                backgroundTimer.Enabled = true;
            }
        }

        public int CurrentAlpha
        {
            get { return currentAlpha; }
            set
            {
                if (value < 0) currentAlpha = 0;
                else if (value > 255) currentAlpha = 255;
                else currentAlpha = value;
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (backgroundTimer != null)
            {
                backgroundTimer.Enabled = false;
                backgroundTimer.Elapsed -= backgroundTimer_Elapsed;
                backgroundTimer.Dispose();
            }
        }

        #endregion

        private void backgroundTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            switch (state)
            {
                    // Fade in
                case 0:
                    CurrentAlpha -= 10;
                    if (CurrentAlpha == 0)
                    {
                        waitCounter = 0;
                        state = 1;
                    }
                    screenSaverForm.Refresh();
                    break;

                    // Wait for counter
                case 1:
                    waitCounter++;
                    if (waitCounter > slideShowDelay)
                        state = 2;
                    break;

                    // Fade out
                default:
                    CurrentAlpha += 10;
                    if (CurrentAlpha == 255)
                    {
                        state = 0;
                        imageSource.Next();
                    }
                    screenSaverForm.Refresh();
                    break;
            }
        }

        public void DoPaint(PaintEventArgs e)
        {
            // Other stuff
            if (started)
            {
                // Calculate size
                RectangleF pos = frame;
                Bitmap bitmap = imageSource.Current;

                pos.Size = bitmap.Size;

                // Height
                if (pos.Height > frame.Height)
                {
                    pos.Height = frame.Height;
                    pos.Width *= frame.Height/bitmap.Height;
                }

                // Width
                if (pos.Width > frame.Width)
                {
                    pos.Width = frame.Width;
                    pos.Height *= frame.Width/bitmap.Width;
                }

                // If alpha
                if (CurrentAlpha > 0)
                {
                    // If we are fading, only use simple interpolation
                    e.Graphics.SmoothingMode = SmoothingMode.None;
                    e.Graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
                }
                else
                {
                    // High quality if normal
                    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
                    e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                }

                // Center image in frame
                pos.Offset((frame.Width - pos.Width)/2, (frame.Height - pos.Height)/2);

                // Draw Image
                e.Graphics.DrawImage(bitmap, pos);

                // Switch back to no SmoothingMode for lines and alpha fake
                e.Graphics.SmoothingMode = SmoothingMode.HighSpeed;

                // Draw Frame
                using (var borderPen = new Pen(Color.WhiteSmoke, 2))
                {
                    pos.Inflate(15, 15);
                    e.Graphics.DrawRectangle(borderPen, pos.X, pos.Y, pos.Width, pos.Height);
                }

                // Do alpha fake
                if (CurrentAlpha > 0)
                {
                    using (Brush backBrush = new SolidBrush(Color.FromArgb(CurrentAlpha, Color.Black)))
                    {
                        pos.Inflate(20, 20);
                        e.Graphics.FillRectangle(backBrush, pos);
                    }
                }
            }
            else
            {
                using (var textFormat = new StringFormat(StringFormatFlags.LineLimit))
                using (Brush brush = new SolidBrush(Color.FromArgb(20, Color.WhiteSmoke)))
                using (var font = new Font("Arial", 96, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Pixel))
                {
                    textFormat.Alignment = StringAlignment.Center;
                    textFormat.LineAlignment = StringAlignment.Center;

                    e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
                    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;

                    e.Graphics.DrawString(infoMessage, font, brush, frame, textFormat);

                    textFormat.Dispose();
                    font.Dispose();
                    brush.Dispose();
                }
            }
        }
    }
}